#! /usr/bin/env python
"""Script to run openlibrary server.

USAGE:

* Run openlibrary http server at port 8080.

    $ ./scripts/openlibrary-server infogami.yml startserver 8080

* Run openlibrary as fastcgi server at port 7070

    $ ./scripts/openlibrary-server infogami.yml startserver fastcgi 8080

* Run openlibrary as gunicorn server at port 8080    

    $ ./scripts/openlibrary-server infogami.yml startserver --gunicorn -b 0.0.0.0:8080    
"""
from __future__ import print_function
import sys
import os
import yaml
from gunicorn.app.base import Application
import web

def setup_env():
    # make sure PYTHON_EGG_CACHE is writable
    os.environ['PYTHON_EGG_CACHE'] = "/tmp/.python-eggs"

    # required when run as fastcgi
    os.environ['REAL_SCRIPT_NAME'] = ""

    sys.path.append('conf')

def start_server():
    import _init_path
    args = sys.argv[1:]
    
    if len(args) < 1 or sys.argv[0] in ['-h', '--help']:
        print("USAGE: %s configfile [subcommand] [arguments]" % (sys.argv[0]), file=sys.stderr)
        sys.exit(1)

    configfile, args = args[0], args[1:]
    load_infogami(configfile)

    import infogami
    infogami.run(args)

def load_infogami(config_file):
    import web
    import infogami
    from infogami import config
    from infogami.utils import delegate

    config.plugin_path += ['openlibrary.plugins']
    config.site = "openlibrary.org"
    
    infogami.load_config(config_file)
    setup_infobase_config(config_file)
    config.middleware.append(https_middleware)

        
def setup_infobase_config(config_file):
    """Reads the infoabse config file and assign it to config.infobase.
    The config_file is used as base to resolve relative path, if specified in the config.
    """
    from infogami import config
    if config.get("infobase_config_file"):
        dir = os.path.dirname(config_file)
        path = os.path.join(dir, config.infobase_config_file)
        config.infobase = yaml.safe_load(open(path).read())

class BaseWSGIServer(Application):
    def __init__(self, config_file):
        self.config_file = config_file
        Application.__init__(self)
    
    def init(self, parser, opts, args):
        pass
        
    def load(self):
        import _init_path
        load_infogami(self.config_file)
        
        import infogami
        import web
        infogami._setup()
        wsgi_app = self.get_wsgi_app()
        # setup middleware for handling /static
        wsgi_app = web.httpserver.StaticMiddleware(wsgi_app)
        return wsgi_app
        
    def get_wsgi_app(self):
        raise NotImplementedError()
        
class OLWSGIServer(BaseWSGIServer):
    def get_wsgi_app(self):
        from infogami import config
        from infogami.utils import delegate

        return delegate.app.wsgifunc(*config.middleware)


def https_middleware(app):
    """Hack to support https even when the app server http only.

    This makes the redirects and web.changequery work correctly with https.

    The nginx configuration has changed to add the following setting:

        proxy_set_header X-Scheme $scheme;

    Using that value to overwrite wsgi.url_scheme in the WSGI environ,
    which is used by all redirects and other utilities.
    """
    def wrapper(environ, start_response):
        if environ.get('HTTP_X_SCHEME') == 'https':
            environ['wsgi.url_scheme'] = 'https'
        return app(environ, start_response)
    return wrapper
    
def main():
    setup_env()

    if "--gunicorn" in sys.argv:
        sys.argv.pop(sys.argv.index("--gunicorn"))        
        configfile = sys.argv.pop(1)
        server = OLWSGIServer(configfile)
        server.run()
    else:
        start_server()
        
if __name__ == "__main__":
    main()
